import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { In, Repository } from 'typeorm';
import { RateModel } from '@/module/rate/rate.model';
import { RateRatingDto, RateShowByLoginDto } from '@/module/rate/rate.dto';
import { UserModel } from '@/module/user/user.model';
import NB from 'number-precision';
import {groupBy} from 'lodash';

@Injectable()
export class RateService {
  constructor(
    @InjectRepository(RateModel)
    private readonly rateModelRepository: Repository<RateModel>,
  ) {}

  async rating(body: RateRatingDto, user: UserModel) {
    const { score, bizUuid } = body;
    
    await this.rateModelRepository.upsert({
      bizUuid,
      userUuid: user.uuid,
      score,
    }, ['bizUuid', 'userUuid'])
  }

  async showByLogin(body: RateShowByLoginDto, user: UserModel) {
    const { bizUuid } = body;
    const current = await this.rateModelRepository.findOne({
      where: {
        bizUuid,
        userUuid: user.uuid,
      },
      select: ['score'],
    });
    const [res] = await this.getBatchRate({bizUuidList: [bizUuid]});
    return {
      ...res,
      currentUserScore: current ? current.score : null,
    }
  }

  async getBatchRate({ bizUuidList }: { bizUuidList: string[] }): Promise<{
    bizUuid: string;
    averageScore: number | null;
    userCount: number;
  }[]> {
    const batchList = await this.rateModelRepository.find({
      where: {
        bizUuid: In(bizUuidList),
      },
    });

    const map = groupBy(batchList, (item)=>{
        return item.bizUuid;
    })

    return Object.keys(map).map(bizUuid=>{
      const list = map[bizUuid];
      if (list.length === 0) {
        return {
          bizUuid,
          averageScore: null,
          userCount: 0,
        };
      }
  
      return {
        bizUuid,
        averageScore: NB.strip(
          list.reduce((total, item) => {
            return total + item.score;
          }, 0) / list.length),
        userCount: list.length
      };
    })
  }
}
